/*
Valentine Gladstein
SOLAR ID 108731583
Homework #1
CSE214
Recitation 03-Phil Ammirato 
Grading TA:Phil Ammirato 
 */

import java.io.*;
import java.util.*;

//The usermanager class stores an array of User objects and provides a number of methods for manipulating them.

public class UserManager {

    public final int MAX_USERS = 50; //Sets the size of the User[] 
    private User[] users;            //Stores the User objects
    private int numUsers;            //Represents the total number of User objects currently stored in this USerManager


/**
 * Constructor instantiates the user[] with a size of MAX_USERS
 *
 */
    public UserManager() {
	users = new User[MAX_USERS];
	numUsers = 0;
    }

/**
 * Returns an cloned object version of the current UserManager
 *
 * @return Object representation of the current UserManager object
 * @note   This method performs a deep copy, so the returned object is completely unique from the original
 */

    public Object clone() {
	UserManager result = new UserManager();
	for (int i = 0; i < numUsers; i++) {
	    User usr = new User(users[i].getUsername(), users[i].getPassword(), users[i].getName(), users[i].getEmail());
	    try {
	    result.addUser(usr, result.size());
	    }
	    catch(Exception e) {}
	}
	return result;
    }


/**
 * Compares this UserManager to another and checks for equality
 *
 * @param obj  The UserManager object to which the current UserManager will be compared
 * @return True if this UserManager is equal to @param. False otherwise.
 */
    public boolean equals(Object obj) {
	if ((obj instanceof UserManager) & (obj != null)) {
	    UserManager managerObj = (UserManager)obj;
	    if (size() != managerObj.size())
		return false;
	    for (int i = 0; i < size(); i++){
		if (!users[i].equals(managerObj.users[i]))
		     return false;		     
	    }
	    return true;
	}
	else return false;
    }


/**
 * Returns the current numberof User objects stored in this UserManager
 *
 * @return The number of users in the UserManager
 */
    public int size() {
	return numUsers;
    }


/**
 * Adds a USer at the indicated position
 *
 * @param  user      The user object to be added to the USerManager
 * @param  position  The position at which the User should be inserted
 * @exception IllegalArgumentExcpetion
 *       Indicates that the position selected is beyond the bounds of the UserManager
 * @exception UserManagerOverflowException
 *       Indicated that the UserManager is full and no more users may be added.
 *
 * @note   The UserManager uses 0-based indexing, so to insert a USer at the head of the list, it must be inserted at position 0
 */
    public void addUser(User user, int position) throws IllegalArgumentException, UserManagerOverflowException{
	if (position < 0 || position > numUsers)
	     throw new IllegalArgumentException();
	    
	if (numUsers >= MAX_USERS)
	   throw new UserManagerOverflowException();

	if (position == numUsers) {
	    users[position] = user;
	}
	else {
	    
	    User tempUser = users[numUsers-1];
	    for (int pos = numUsers-1; pos > position; pos--) {
		users[pos] = users[pos-1];
	    }
	    users[numUsers] = tempUser;
	    users[position] = user;
	}	    
	numUsers++;    
    }
    
    
    public void removeUser(int position) throws IllegalArgumentException{
	if (position < 0 || position >= numUsers)
	    throw new IllegalArgumentException();
	for (int i = position; i < numUsers-1; i++) {
	    users[i] = users[i+1];
	}
	numUsers--;
    }

/**
 * Returns the user at the specified position
 *
 * @param  position  The psoition from which to return a user
 * @return  The User object at the specified position
 *
 * @exception IllegalArgumentxception
 *         Indicated that the @param is beyond the scope of the USerManager
 */
    public User getUser(int position) throws IllegalArgumentException {
	if (position < 0 || position >= numUsers)
            throw new IllegalArgumentException();
	return users[position];
    }


/**
 * Gets the String representation of this USerManager object, neatly formatted into rows and columns
 *
 * @return Formatted String representing the current USerManager object and all of the USer objects it contains
 */
    public String toString() {
	String result = "------------------------------------------------------------------------------------------------------------------------\n";
	    result += String.format("%-25s%-24s%-35s%-25s", "username", "password", "email", "name")+"\n";
	result += "------------------------------------------------------------------------------------------------------------------------\n";
	for (int i = 0; i < numUsers; i++) {
	    result += users[i].toString() + "\n";
	}
	return result;
    }
    

/**
 * Calls the toString() method and uses it to print all users to the standard output
 *
 */
    public void printAllUsers() {
	System.out.println("");
	System.out.println(toString());
    }


/**
 * Overloaded. Checks whether a user with the specified username and password exists in this UserMAnager, printing the result to the standard output.
 *
 * @param username  The user's username 
 * @param password  The user's password
 */
    public static void login(String username, String password, UserManager manager){
	for (int i = 0; i < manager.numUsers; i++) {
	    if (manager.users[i].getUsername().equals(username) && manager.users[i].getPassword().equals(password)) {
		System.out.println("Login Successful! " + username + " has been logged in.");
		return; 
	    }
	}
    System.out.println("Login failed. Please try again.");
    }


/**
 * Overloaded. This method provides a more convinient way to call the login() method with fewer parameters.
 *
 * @param username  The user's username 
 * @param password  The user's password
 */
    public void login(String username, String password) {
	login(username, password, this);
    }

    public class IllegalArgumentException extends Exception {
	
	public IllegalArgumentException() {
	}
    }
    
    public class UserManagerOverflowException extends Exception {
	
	public UserManagerOverflowException() {
	}
    }
}
